<?php
/**********************************************************************
 *                                                                    *    
 * Copyright (c) 2009 Dmytro Bezhnar. All rights reserved.     *
 *                                                                    *
 **********************************************************************/

/**
 * Ageset entity manager.
 *
 * @version $Id: SitemapManager.php,v 1.19 2008/07/08 15:22:33 master Exp $
 */
class SitemapManager extends ORMManager {
	
	#public $index_count = 50000;
	
	public $max_index_count = 50000;
	
	public $max_file_size = 10000000;
	
	public $max_item_size = 10000;
	
	public $dir = './';
	
	public $indexFilename = 'sitemap.xml';

	public $filemask = 'sitemap_part#part#.xml';
	
	public $site_url = 'http://ria.ua/';
	
	public $lang_prefix;
	
	public $gzip_enable = true;
	
	public $gzip_ext = '.gz';
	
	

	private $parts = 0;
	
	private $item = 0;
	
	public $count_all = 0;

	public $items = 0;
	
	private $buffer_size = 8192;
	
	private $lng_sections;
	
	private $part_size;

	private $file_template_size = 200;
	
	/**
	 * @var TreeManager
	 */
	private $d_tree;
	
	private $written_lines = 0;
	
	
	/**
	 * Rules for prepare sitemap
	 *
	 * @return unknown
	 */
	public function getRules() {
		$sitemp_tree = new Sitemap_treeDB(); 
		$qs = "SELECT sm_target, sm_event from ".$sitemp_tree->__table." where sm_target != '' and sm_event != '' and is_active";
		return $this->getArray($qs);
	}
	
	
	
	/**
	 * Return area_id for specified target and event
	 *
	 * @param str $target
	 * @param str $event
	 * @return int
	 */
	public function getAreaIdByTargetEvent($target='', $event='') {
		$sitemp_tree = new Sitemap_treeDB(); 
		if ($target != '' && $event != ''){
			$qs = "SELECT area_id as count from ".$sitemp_tree->__table." where sm_target = '$target' and sm_event = '$event'";
			return $this->getCount($qs);
		}
		return -1;
	}
	
	/**
	 * Sitemap generator
	 *
	 */
	public function genSitemap() {
		$this->makeLangPrefixes();
		$this->_parceItems();
		$this->_load_sections_arr();
		
		while ($this->item < $this->items) {
			$cnt = $this->_writePart($this->item);
			$this->item += $cnt;
			$this->parts++;
			if ($this->parts > $this->max_item_size) {
				exit();
			}
			
		}
		
		
		#for($i=0;$i<$this->parts;$i++) {
		#	$this->_writePart($i,$this->index_count);
		#}
		
		$this->_writeSitemapIndex();
	}
	
	public function makeLangPrefixes() {
		$qs = "select lang_code, concat(lang_code,'/') as prefix from lang where active";
		$this->lang_prefix = $this->getAssArray($qs,'lang_code','prefix');
		$this->lang_prefix[$GLOBALS['options']['multilanguage']['lang']] = '';
		//return $this->lang_prefix;
	}
	
	/**
	 * Get max priority for target area_id
	 *
	 * @param int $area_id
	 * @return float
	 */
	public function getMaxPriority($area_id) {
		if (!isset($this->d_tree)) {
			$this->create_tree();
		}
		#print_r($this->d_tree);
		if (isset($this->d_tree->tree_idx[$area_id])) {
			$max_priority = $this->d_tree->tree_idx[$area_id]['max_priority'];
		} else {
			return 0.5;
		}
		if ($max_priority == 0) {
			$max_priority = $this->getMaxPriority($this->d_tree->tree_idx[$area_id]['parent_id']);
		}
		return $max_priority;
	}
	
	/**
	 * Clear all items for specified area_id
	 *
	 * @param int $area_id
	 * @return int
	 */
	public function clearSitemapItems($area_id) {
		$sitemap_obj = new SitemapDB();
		$qs = "delete FROM ".$sitemap_obj->__table." where area_id=".$area_id;
		return $this->execQuery($qs);
	}
	
	/**
	 * Return SitemapDB object by specified page_id
	 * If page_id not specified - return empty object
	 *
	 * @param int $page_id
	 * @return SitemapDB
	 */
	public function getSitemapItem($page_id=0) {
		$sitemap_obj = new SitemapDB();
		if ($page_id){
			$sitemap_obj->page_id = $page_id;
			$this->find($sitemap_obj);
		}
		return $sitemap_obj;
	}
	
	/**
	 * Insert new Sitemap record into SitemapDB return page_id from created item
	 *
	 * @param SitemapDB $sitemap_obj
	 * @return int
	 */
	public function insertSitemapItem($sitemap_obj){
		$qs = "select loc as count from sitemap where loc='$sitemap_obj->loc'";
		if (!$this->getCount($qs)){
			$this->save($sitemap_obj);
			return $sitemap_obj->page_id;
		} else {
			print" !Dublicate loc fied = $sitemap_obj->loc ";
		}
		return 0;
	}
	
	
	
	private function _parceItems() {
		$sitemap = new SitemapDB();
		$qs = "SELECT count(*) as `count` from ".$sitemap->__table;
		$this->items = $this->getCount($qs);
	}
		

	/**
	 * Write Sitemap Part
	 *
	 * @param integer $start_item
	 * @param integer $limit
	 */
	private function _writePart($start_pos) {
		$sitemap = new SitemapDB();
		$limit = $this->max_index_count;
		$this->part_size = 0;
		$this->written_lines = 0; 
		
		$max_item_size = $this->max_file_size - $this->max_item_size - $this->file_template_size;
		$max_index_count = $this->max_index_count - count($this->lang_prefix);
				
		$qs = 'SELECT loc, date_format(lastmod, "%Y-%m-%dT%H:%i+02:00") as lastmod , changefreq, priority, area_id from '.$sitemap->__table." limit $start_pos, $limit";
		$items = $this->getArray($qs);
		$max_i = count($items);
		
		$filename = preg_replace('/\#part\#/',$this->parts,$this->filemask);
		
		$fh = fopen($this->dir.$filename,'w');
		
		fwrite($fh, $this->_makeSitemapHeader());
		
		$i = 0;
		while (	($this->written_lines <= $max_index_count) 
			and ($this->part_size <= $max_item_size)
			and ($i < $max_i))
		{
			$item = $items[$i];
			$area_id = $item['area_id'];
			unset($item['area_id']);
			if ($this->lng_sections[$area_id]) {
				foreach ($this->lang_prefix as $lang => $prefix) {
					$this->_writeLine($fh,$item,$prefix);
				}
			} else {
				$this->_writeLine($fh,$item,$prefix);
			}
			$i++;
		}
	
		fwrite($fh, $this->_makeSitemapFooter());
		fclose($fh);
		
		return $i; 
	}
	
	private function _makeSitemapHeader() {
		return '<?xml version="1.0" encoding="UTF-8"?>'."\n".'<urlset xmlns="http://www.google.com/schemas/sitemap/0.84">'."\n";
	}
	
	private function _makeSitemapFooter() {
		return '</urlset>';
	}
	
	private function _writeLine($fh,$item,$lang_prefix) {
			$line_section = "<url>\n";
			foreach ($item as $key => $value) {
				if ($key == 'loc') {
					$value = $this->site_url.$lang_prefix.$value;#urlencode($value);
				} 
				$line_section .= "\t<$key>$value</$key>\n";
			}
			$line_section .= "</url>\n";
			fwrite($fh, $line_section);
			
			$this->part_size += strlen($line_section);
			$this->written_lines++;
			$this->count_all++;
	}
	
	
	
	/**
	 * Write Sitemap Index file
	 *
	 */
	private function _writeSitemapIndex() {
		$fh = fopen($this->dir.$this->indexFilename,'w');
		
		fwrite($fh, $this->_makeSitemapIndexHeader());
		
		$lastmod = $this->getCount('SELECT date_format(now(), "%Y-%m-%dT%H:%i+02:00") as count');
		
		for($i=0;$i<$this->parts;$i++) {
			fwrite($fh, "<sitemap>\n");
			$filename = preg_replace('/\#part\#/',$i,$this->filemask);
			if ($this->gzip_enable) {
				$this->make_gzip($filename);
				$filename = $filename.$this->gzip_ext;
			}
			fwrite($fh, "\t<loc>".$this->site_url.$filename."</loc>\n");
			fwrite($fh, "\t<lastmod>$lastmod</lastmod>\n");
			fwrite($fh, "</sitemap>\n");
		}
		
		fwrite($fh, $this->_makeSitemapIndexFooter());
		fclose($fh);
	}

	private function _makeSitemapIndexHeader() {
		return '<?xml version="1.0" encoding="UTF-8"?>'."\n".'<sitemapindex xmlns="http://www.google.com/schemas/sitemap/0.84">'."\n";
	}
	
	private function _makeSitemapIndexFooter() {
		return '</sitemapindex>';
	}

	private function make_gzip($filename) {
		$fh = fopen($this->dir.$filename,'r');
		$zd = gzopen($this->dir.$filename.$this->gzip_ext,'w');
		
		while (!feof($fh)) {
  			gzwrite($zd,fread($fh, $this->buffer_size),$this->buffer_size);
		}
		
		fclose($fh);
		gzclose($zd);
		unlink($this->dir.$filename);
	}
	
	private function _load_sections_arr() {
		$sitemp_tree = new Sitemap_treeDB(); 
		$qs = "SELECT area_id, multi_lang from ".$sitemp_tree->__table;
		$this->lng_sections = $this->getAssArray($qs,'area_id','multi_lang');
	}
	
	private function create_tree() {
		$sitemp_tree = new Sitemap_treeDB();
		$this->d_tree = new TreeManager(new stdClass(),'d',$sitemp_tree->__table);
		$this->d_tree->table_fields = array(
			'id'			=> 'area_id',
			'parent_id'		=> 'parent_id',
			'prio'			=> 'prio',
			'type'			=> 'type',
			'sm_target'		=> 'sm_target',
			'sm_event'		=> 'sm_event',
			'is_active'		=> 'is_active',
			'multi_lang'	=> 'multi_lang',
			'max_priority'	=> 'max_priority'
		);
		$this->d_tree->makeSortedClientTree();
	}
	
}
?>